package czopyk.model.factories;

import cern.jet.random.engine.RandomEngine;
import czopyk.model.structure.Center;
import czopyk.model.structure.CenterClass;

public class CenterFactory {

	public static int TYPE_COMMON = 0;
	public static int TYPE_CACHE = 1 << 1;
	public static int TYPE_LOAD_BALANCER = 1 << 2;

	RandomEngine re;

	private RandomEngine getRe() {
		if (re == null) {
			re = Utils.getNewRandomEngine();
		}
		return re;
	}

	public Center getCenter(String name, final CenterClass cc,
			final int channels, final int type,
			final Double hitRate) {

		if (cc == null) {
			throw new IllegalArgumentException("Center class can not be null.");
		}

		if (channels < 1) {
			throw new IllegalArgumentException("Number of cores must be positive.");
		}

		if (((type & TYPE_CACHE) != 0)) {
			if (hitRate == null) {
				throw new IllegalArgumentException(
						"Cache must specify hit rate parameter.");
			} else if (hitRate < 0.0 || hitRate > 1.0) {
				throw new IllegalArgumentException("Hit rate must be 0.0 <= ? <= 1.0.");
			}
		}

		if ((type & TYPE_CACHE & TYPE_LOAD_BALANCER) != 0) {
			Cache c = new CacheLoadBalancer(name, channels, cc);
			c.setHitRate(hitRate);
			return c;
		} else if ((type & TYPE_LOAD_BALANCER) != 0) {
			return new LoadBalancer(name, channels, cc);
		} else if ((type & TYPE_CACHE) != 0) {
			Cache c = new Cache(name, channels, cc);
			c.setHitRate(hitRate);
			return c;
		} else {
			return new Center(name, channels, cc);
		}
	}

	private class Cache extends Center implements czopyk.model.structure.Cache {

		private double hitRate;

		private final RandomEngine re = Utils.getNewRandomEngine();

		public Cache(String name, int channels, CenterClass cc) {
			super(name, channels, cc);
		}

		public double getHitRate() {
			return hitRate;
		}

		public void setHitRate(double hitRate) {
			this.hitRate = hitRate;
		}

		public boolean skip() {
			return hitRate < re.nextDouble();
		}
	}

	private class CacheLoadBalancer extends Cache implements
			czopyk.model.structure.LoadBalancer {
		public CacheLoadBalancer(String name, int channels, CenterClass cc) {
			super(name, channels, cc);
		}
	}

	private class LoadBalancer extends Center implements
			czopyk.model.structure.LoadBalancer {
		public LoadBalancer(String name, int channels, CenterClass cc) {
			super(name, channels, cc);
		}
	}

}
